/**
 * 
 */
package javapop.framework.parser.tuple;

import java.util.List;

import javapop.framework.ParseContext;
import javapop.framework.ParseError;
import javapop.framework.ParseInput;
import javapop.framework.ParseResult;
import javapop.framework.Parser;
import javapop.framework.parser.TupleParser;
import javapop.utils.Nonuple;

/**
 * @author Hakim Belhaouari
 *
 */
public class Nine<A, B, C, D, E, F, G, H, I> extends Parser<Nonuple<A, B, C, D, E, F, G, H, I>> {

	private TupleParser parser;
	
	/**
	 * 
	 */
	public Nine() {
		parser = new TupleParser();
		
	}

	public Nine<A, B, C, D, E, F, G, H, I> then(Parser<?> silent) {
		parser.addSilent(silent);
		return this;
	}
	
	public Nine<A, B, C, D, E, F, G, H, I> first(Parser<A> first) {
		if(parser.getArity()>=1) {
			throw new IllegalStateException("First component already set");
		}
		parser.addComponent(first);
		return this;
	}
	
	public Nine<A, B, C, D, E, F, G, H, I> second(Parser<B> first) {
		if(parser.getArity()==0) {
			throw new IllegalStateException("First component missing");
		}
		if(parser.getArity()>1) {
			throw new IllegalStateException("Second component already set");
		}
		parser.addComponent(first);
		return this;
	}

	public Nine<A, B, C, D, E, F, G, H, I> third(Parser<C> first) {
		if(parser.getArity()==0) {
			throw new IllegalStateException("First component missing");
		}
		if(parser.getArity()==1) {
			throw new IllegalStateException("Second component missing");
		}
		if(parser.getArity()>2) {
			throw new IllegalStateException("Third component already set");
		}
		parser.addComponent(first);
		return this;
	}
	
	public Nine<A, B, C, D, E, F, G, H, I> fourth(Parser<D> p) {
		if(parser.getArity()==0) {
			throw new IllegalStateException("First component missing");
		}
		if(parser.getArity()==1) {
			throw new IllegalStateException("Second component missing");
		}
		if(parser.getArity()==2) {
			throw new IllegalStateException("Third component missing");
		}
		if(parser.getArity() > 3) {
			throw new IllegalStateException("Fourth component already set");
		}
		parser.addComponent(p);
		return this;
	}
	
	public Nine<A, B, C, D, E, F, G, H, I> fifth(Parser<E> p) {
		if(parser.getArity()==0) {
			throw new IllegalStateException("First component missing");
		}
		if(parser.getArity()==1) {
			throw new IllegalStateException("Second component missing");
		}
		if(parser.getArity()==2) {
			throw new IllegalStateException("Third component missing");
		}
		if(parser.getArity()==3) {
			throw new IllegalStateException("Fourth component missing");
		}
		if(parser.getArity() > 4) {
			throw new IllegalStateException("Fifth component already set");
		}
		parser.addComponent(p);
		return this;
	}
	
	public Nine<A, B, C, D, E, F, G, H, I> sixth(Parser<F> p) {
		if(parser.getArity()==0) {
			throw new IllegalStateException("First component missing");
		}
		if(parser.getArity()==1) {
			throw new IllegalStateException("Second component missing");
		}
		if(parser.getArity()==2) {
			throw new IllegalStateException("Third component missing");
		}
		if(parser.getArity()==3) {
			throw new IllegalStateException("Fourth component missing");
		}
		if(parser.getArity()==4) {
			throw new IllegalStateException("Fifth component missing");
		}
		if(parser.getArity() > 5) {
			throw new IllegalStateException("Sexth component already set");
		}
		parser.addComponent(p);
		return this;
	}
	
	public Nine<A, B, C, D, E, F, G, H, I> seventh(Parser<G> p) {
		if(parser.getArity()==0) {
			throw new IllegalStateException("First component missing");
		}
		if(parser.getArity()==1) {
			throw new IllegalStateException("Second component missing");
		}
		if(parser.getArity()==2) {
			throw new IllegalStateException("Third component missing");
		}
		if(parser.getArity()==3) {
			throw new IllegalStateException("Fourth component missing");
		}
		if(parser.getArity()==4) {
			throw new IllegalStateException("Fifth component missing");
		}
		if(parser.getArity()==5) {
			throw new IllegalStateException("Sexth component missing");
		}
		if(parser.getArity() > 6) {
			throw new IllegalStateException("Seventh component already set");
		}
		parser.addComponent(p);
		return this;
	}
	
	public Nine<A, B, C, D, E, F, G, H, I> eighth(Parser<H> p) {
		if(parser.getArity()==0) {
			throw new IllegalStateException("First component missing");
		}
		if(parser.getArity()==1) {
			throw new IllegalStateException("Second component missing");
		}
		if(parser.getArity()==2) {
			throw new IllegalStateException("Third component missing");
		}
		if(parser.getArity()==3) {
			throw new IllegalStateException("Fourth component missing");
		}
		if(parser.getArity()==4) {
			throw new IllegalStateException("Fifth component missing");
		}
		if(parser.getArity()==5) {
			throw new IllegalStateException("Sixth component missing");
		}
		if(parser.getArity()==6) {
			throw new IllegalStateException("Seventh component missing");
		}
		if(parser.getArity() > 7) {
			throw new IllegalStateException("Heighth component already set");
		}
		parser.addComponent(p);
		return this;
	}

	public Nine<A, B, C, D, E, F, G, H, I> ninth(Parser<I> p) {
		if(parser.getArity()==0) {
			throw new IllegalStateException("First component missing");
		}
		if(parser.getArity()==1) {
			throw new IllegalStateException("Second component missing");
		}
		if(parser.getArity()==2) {
			throw new IllegalStateException("Third component missing");
		}
		if(parser.getArity()==3) {
			throw new IllegalStateException("Fourth component missing");
		}
		if(parser.getArity()==4) {
			throw new IllegalStateException("Fifth component missing");
		}
		if(parser.getArity()==5) {
			throw new IllegalStateException("Sixth component missing");
		}
		if(parser.getArity()==6) {
			throw new IllegalStateException("Seventh component missing");
		}
		if(parser.getArity()==7) {
			throw new IllegalStateException("Eighth component missing");
		}
		if(parser.getArity() > 8) {
			throw new IllegalStateException("Ninth component already set");
		}
		parser.addComponent(p);
		return this;
	}

	public Nine<A, B, C, D, E, F, G, H, I> fatalFrom(int ref) {
		parser.setFatalFrom(ref);
		return this;
	}

	/**
	 * @see javapop.framework.Parser#eval(javapop.framework.ParseContext, javapop.framework.ParseInput)
	 */
	@SuppressWarnings("unchecked")
	@Override
	public ParseResult eval(ParseContext ctx, ParseInput input) {
		ParseResult<List<?>> result = parser.parse(ctx, input);
		if(result.isError()) {
			return (ParseResult) result.asError();
		}
		List<?> results = result.getResult();
		if(results.size()!=9) {
			return (ParseResult) new ParseError("Wrong cardinality: expected 9 got "+results.size());
		}
		A a = (A) results.get(0);
		B b = (B) results.get(1);
		C c = (C) results.get(2);
		D d = (D) results.get(3);
		E e = (E) results.get(4);
		F f = (F) results.get(5);
		G g = (G) results.get(6);
		H h = (H) results.get(7);
		I i = (I) results.get(8);
		
		Nonuple<A, B, C, D, E, F, G, H, I> triple = new Nonuple<A, B, C, D, E, F, G, H, I>(a,b,c,d,e,f,g,h,i);
		return buildResult(triple);
	}

	/**
	 * @see javapop.framework.Parser#getDescription()
	 */
	@Override
	public String getDescription() {
		return parser.getDescription();
	}
	
	@Override
	public boolean isMemoized() {
		return false;
	}


}
